package com.oceansoft.core.message;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.HashMap;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

/**
 * 生成签名类
 * 
 * @author wuch
 * 
 */

public class TokenUtil {

	/**
	 * URL编码 (符合FRC1738规范)
	 * 
	 * @param input
	 *            待编码的字符串
	 * @return 编码后的字符串
	 * @throws ApiException
	 *             不支持指定编码时抛出异常。
	 */
	public static String encodeUrl(String input) throws ApiException {
		try {
			return URLEncoder.encode(input, CONTENT_CHARSET)
					.replace("+", "%20").replace("*", "%2A");
		} catch (UnsupportedEncodingException e) {
			throw new ApiException(ErrorCode.MAKE_SIGNATURE_ERROR, e);
		}
	}

	/**
	 * 生成签名
	 * 
	 * @param method
	 *            HTTP请求方法 "get" / "post"
	 * 
	 * @param appkey
	 *            密钥
	 * 
	 * @return 签名值
	 * 
	 * @throws ApiException不支持指定编码以及不支持指定的加密方法时抛出异常
	 *             。
	 */
	public static String makeToken(String url_path,
			HashMap<String, String> params, String appkey) throws ApiException {
		String sig = null;
		try {
			Mac mac = Mac.getInstance(HMAC_ALGORITHM);

			SecretKeySpec secretKey = new SecretKeySpec(
					appkey.getBytes(CONTENT_CHARSET), mac.getAlgorithm());

			mac.init(secretKey);

			String mk = makeSource(url_path, params);

			byte[] hash = mac.doFinal(mk.getBytes(CONTENT_CHARSET));

			// base64
			sig = new String(Base64.encodeBytes(hash));
		} catch (NoSuchAlgorithmException e) {
			throw new ApiException(ErrorCode.MAKE_SIGNATURE_ERROR, e);
		} catch (UnsupportedEncodingException e) {
			throw new ApiException(ErrorCode.MAKE_SIGNATURE_ERROR, e);
		} catch (InvalidKeyException e) {
			throw new ApiException(ErrorCode.MAKE_SIGNATURE_ERROR, e);
		}
		return sig;
	}

	/**
	 * 生成签名所需源串
	 * 
	 * 
	 * @param params
	 *            URL请求参数
	 * 
	 * @return 签名所需源串
	 */
	public static String makeSource(String url_path,
			HashMap<String, String> params) throws ApiException {
		Object[] keys = params.keySet().toArray();

		Arrays.sort(keys);

		StringBuilder buffer = new StringBuilder(128);

		buffer.append(encodeUrl(url_path)).append("&");

		StringBuilder buffer2 = new StringBuilder();

		for (int i = 0; i < keys.length; i++) {
			buffer2.append(keys[i]).append("=").append(params.get(keys[i]));

			if (i != keys.length - 1) {
				buffer2.append("&");
			}
		}

		buffer.append(encodeUrl(buffer2.toString()));

		return buffer.toString();
	}

	public static boolean verifyToken(String url_path,
			HashMap<String, String> params, String appkey, String token)
			throws ApiException {
		// 确保不含token
		params.remove("token");

		// 计算签名
		String token_new = makeToken(url_path, params, appkey);

		return token_new.equals(token);
	}

	// 编码方式
	private static final String CONTENT_CHARSET = "UTF-8";

	// HMAC算法
	private static final String HMAC_ALGORITHM = "HmacSHA1";
	
	
	
}
